ನಿಮ್ಮ ಪೈಥಾನ್ ಕೋಡ್ನ ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ಹಲವು ಪಟ್ಟು ಹೆಚ್ಚಿಸಿ. ಈ ಸಮಗ್ರ ಮಾರ್ಗದರ್ಶಿ ಜಾಗತಿಕ ಡೆವಲಪರ್ಗಳಿಗಾಗಿ ಸಿಮ್ಡಿ, ವೆಕ್ಟರೈಸೇಶನ್, ನಂಪೈ ಮತ್ತು ಸುಧಾರಿತ ಲೈಬ್ರರಿಗಳನ್ನು ವಿವರಿಸುತ್ತದೆ.
ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ಹೆಚ್ಚಿಸುವುದು: ಪೈಥಾನ್ ಸಿಮ್ಡಿ ಮತ್ತು ವೆಕ್ಟರೈಸೇಶನ್ ಕುರಿತ ಸಮಗ್ರ ಮಾರ್ಗದರ್ಶಿ
ಕಂಪ್ಯೂಟಿಂಗ್ ಜಗತ್ತಿನಲ್ಲಿ, ವೇಗವು ಅತ್ಯಂತ ಮುಖ್ಯವಾಗಿದೆ. ನೀವು ಮಷೀನ್ ಲರ್ನಿಂಗ್ ಮಾದರಿಯನ್ನು ತರಬೇತುಗೊಳಿಸುತ್ತಿರುವ ಡೇಟಾ ವಿಜ್ಞಾನಿಯಾಗಿರಲಿ, ಸಿಮ್ಯುಲೇಶನ್ ನಡೆಸುತ್ತಿರುವ ಹಣಕಾಸು ವಿಶ್ಲೇಷಕರಾಗಿರಲಿ, ಅಥವಾ ದೊಡ್ಡ ಡೇಟಾಸೆಟ್ಗಳನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸುತ್ತಿರುವ ಸಾಫ್ಟ್ವೇರ್ ಇಂಜಿನಿಯರ್ ಆಗಿರಲಿ, ನಿಮ್ಮ ಕೋಡ್ನ ದಕ್ಷತೆಯು ಉತ್ಪಾದಕತೆ ಮತ್ತು ಸಂಪನ್ಮೂಲ ಬಳಕೆಯ ಮೇಲೆ ನೇರ ಪರಿಣಾಮ ಬೀರುತ್ತದೆ. ಪೈಥಾನ್, ಅದರ ಸರಳತೆ ಮತ್ತು ಓದಲು ಸುಲಭವಾದ ಗುಣಕ್ಕಾಗಿ ಪ್ರಶಂಸಿಸಲ್ಪಟ್ಟಿದೆ, ಆದರೆ ಅದಕ್ಕೊಂದು ಅಕಿಲ್ಸ್ ಹೀಲ್ ಇದೆ: ಕಂಪ್ಯೂಟೇಶನಾತ್ಮಕವಾಗಿ ತೀವ್ರವಾದ ಕಾರ್ಯಗಳಲ್ಲಿ, ವಿಶೇಷವಾಗಿ ಲೂಪ್ಗಳನ್ನು ಒಳಗೊಂಡಿರುವ ಕಾರ್ಯಗಳಲ್ಲಿ ಅದರ ಕಾರ್ಯಕ್ಷಮತೆ ಕಡಿಮೆ. ಆದರೆ ಡೇಟಾದ ಪ್ರತಿಯೊಂದು ಅಂಶವನ್ನು ಒಂದೊಂದಾಗಿ ಕಾರ್ಯಗತಗೊಳಿಸುವ ಬದಲು, ಸಂಪೂರ್ಣ ಡೇಟಾ ಸಂಗ್ರಹದ ಮೇಲೆ ಏಕಕಾಲದಲ್ಲಿ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು ನಡೆಸಲು ಸಾಧ್ಯವಾದರೆ? ಇದೇ ವೆಕ್ಟರೈಸ್ಡ್ ಕಂಪ್ಯೂಟೇಶನ್ನ ಭರವಸೆ, ಇದು ಸಿಪಿಯುನ ಸಿಮ್ಡಿ (SIMD) ಎಂಬ ವೈಶಿಷ್ಟ್ಯದಿಂದ ಚಾಲಿತವಾದ ಒಂದು ಮಾದರಿಯಾಗಿದೆ.
ಈ ಮಾರ್ಗದರ್ಶಿ ನಿಮ್ಮನ್ನು ಪೈಥಾನ್ನಲ್ಲಿ ಸಿಂಗಲ್ ಇನ್ಸ್ಟ್ರಕ್ಷನ್, ಮಲ್ಟಿಪಲ್ ಡೇಟಾ (SIMD) ಕಾರ್ಯಾಚರಣೆಗಳು ಮತ್ತು ವೆಕ್ಟರೈಸೇಶನ್ ಪ್ರಪಂಚದ ಆಳಕ್ಕೆ ಕರೆದೊಯ್ಯುತ್ತದೆ. ನಾವು ಸಿಪಿಯು ಆರ್ಕಿಟೆಕ್ಚರ್ನ ಮೂಲಭೂತ ಪರಿಕಲ್ಪನೆಗಳಿಂದ ಹಿಡಿದು ನಂಪೈ (NumPy), ನಂಬಾ (Numba), ಮತ್ತು ಸೈಥಾನ್ (Cython) ನಂತಹ ಶಕ್ತಿಯುತ ಲೈಬ್ರರಿಗಳ ಪ್ರಾಯೋಗಿಕ ಅನ್ವಯದವರೆಗೆ ಪ್ರಯಾಣಿಸುತ್ತೇವೆ. ನಿಮ್ಮ ಭೌಗೋಳಿಕ ಸ್ಥಳ ಅಥವಾ ಹಿನ್ನೆಲೆಯನ್ನು ಲೆಕ್ಕಿಸದೆ, ನಿಮ್ಮ ನಿಧಾನಗತಿಯ, ಲೂಪಿಂಗ್ ಪೈಥಾನ್ ಕೋಡ್ ಅನ್ನು ಹೆಚ್ಚು ಆಪ್ಟಿಮೈಸ್ ಮಾಡಿದ, ಉನ್ನತ-ಕಾರ್ಯಕ್ಷಮತೆಯ ಅಪ್ಲಿಕೇಶನ್ಗಳಾಗಿ ಪರಿವರ್ತಿಸಲು ಬೇಕಾದ ಜ್ಞಾನವನ್ನು ನಿಮಗೆ ನೀಡುವುದು ನಮ್ಮ ಗುರಿಯಾಗಿದೆ.
ಅಡಿಪಾಯ: ಸಿಪಿಯು ಆರ್ಕಿಟೆಕ್ಚರ್ ಮತ್ತು ಸಿಮ್ಡಿ (SIMD) ಯನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವುದು
ವೆಕ್ಟರೈಸೇಶನ್ನ ಶಕ್ತಿಯನ್ನು ನಿಜವಾಗಿಯೂ ಪ್ರಶಂಸಿಸಲು, ನಾವು ಮೊದಲು ಆಧುನಿಕ ಸೆಂಟ್ರಲ್ ಪ್ರೊಸೆಸಿಂಗ್ ಯೂನಿಟ್ (CPU) ಹೇಗೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ ಎಂಬುದನ್ನು ನೋಡಬೇಕು. ಸಿಮ್ಡಿಯ ಮ್ಯಾಜಿಕ್ ಯಾವುದೇ ಸಾಫ್ಟ್ವೇರ್ ತಂತ್ರವಲ್ಲ; ಇದು ಹಾರ್ಡ್ವೇರ್ ಸಾಮರ್ಥ್ಯವಾಗಿದ್ದು, ಸಂಖ್ಯಾತ್ಮಕ ಕಂಪ್ಯೂಟಿಂಗ್ನಲ್ಲಿ ಕ್ರಾಂತಿಯನ್ನುಂಟುಮಾಡಿದೆ.
ಎಸ್ಐಎಸ್ಡಿ (SISD) ಯಿಂದ ಸಿಮ್ಡಿ (SIMD) ಗೆ: ಗಣನೆಯಲ್ಲಿ ಒಂದು ಮಾದರಿ ಬದಲಾವಣೆ
ಅನೇಕ ವರ್ಷಗಳಿಂದ, ಗಣನೆಯ ಪ್ರಬಲ ಮಾದರಿಯು ಎಸ್ಐಎಸ್ಡಿ (ಸಿಂಗಲ್ ಇನ್ಸ್ಟ್ರಕ್ಷನ್, ಸಿಂಗಲ್ ಡೇಟಾ) ಆಗಿತ್ತು. ಒಬ್ಬ ಬಾಣಸಿಗ ಒಂದು ಸಮಯದಲ್ಲಿ ಒಂದೇ ತರಕಾರಿಯನ್ನು ನಿಖರವಾಗಿ ಕತ್ತರಿಸುವುದನ್ನು ಕಲ್ಪಿಸಿಕೊಳ್ಳಿ. ಬಾಣಸಿಗನಿಗೆ ಒಂದು ಸೂಚನೆ ("ಕತ್ತರಿಸು") ಮತ್ತು ಒಂದು ಡೇಟಾ ತುಣುಕಿನ (ಒಂದು ಕ್ಯಾರೆಟ್) ಮೇಲೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತಾನೆ. ಇದು ಸಾಂಪ್ರದಾಯಿಕ ಸಿಪಿಯು ಕೋರ್ ಪ್ರತಿ ಚಕ್ರಕ್ಕೆ ಒಂದು ಡೇಟಾ ತುಣುಕಿನ ಮೇಲೆ ಒಂದು ಸೂಚನೆಯನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸುವುದಕ್ಕೆ ಸಮಾನವಾಗಿದೆ. ಎರಡು ಪಟ್ಟಿಗಳಿಂದ ಸಂಖ್ಯೆಗಳನ್ನು ಒಂದೊಂದಾಗಿ ಸೇರಿಸುವ ಒಂದು ಸರಳ ಪೈಥಾನ್ ಲೂಪ್ ಎಸ್ಐಎಸ್ಡಿ ಮಾದರಿಯ ಪರಿಪೂರ್ಣ ಉದಾಹರಣೆಯಾಗಿದೆ:
# ಕಾನ್ಸೆಪ್ಚುವಲ್ SISD ಕಾರ್ಯಾಚರಣೆ
result = []
for i in range(len(list_a)):
# ಒಂದು ಸಮಯದಲ್ಲಿ ಒಂದು ಡೇಟಾ ತುಣುಕಿನ ಮೇಲೆ (a[i], b[i]) ಒಂದು ಸೂಚನೆ (ಸೇರಿಸು)
result.append(list_a[i] + list_b[i])
ಈ ವಿಧಾನವು ಅನುಕ್ರಮವಾಗಿದೆ ಮತ್ತು ಪ್ರತಿ ಪುನರಾವರ್ತನೆಗೆ ಪೈಥಾನ್ ಇಂಟರ್ಪ್ರಿಟರ್ನಿಂದ ಗಮನಾರ್ಹ ಓವರ್ಹೆಡ್ ಅನ್ನು ಉಂಟುಮಾಡುತ್ತದೆ. ಈಗ, ಆ ಬಾಣಸಿಗನಿಗೆ ಒಂದು ವಿಶೇಷ ಯಂತ್ರವನ್ನು ನೀಡಲಾಗಿದೆ ಎಂದು ಕಲ್ಪಿಸಿಕೊಳ್ಳಿ, ಅದು ಒಂದೇ ಲಿವರ್ ಎಳೆಯುವ ಮೂಲಕ ಏಕಕಾಲದಲ್ಲಿ ನಾಲ್ಕು ಕ್ಯಾರೆಟ್ಗಳ ಸಾಲನ್ನು ಕತ್ತರಿಸಬಲ್ಲದು. ಇದೇ ಸಿಮ್ಡಿ (ಸಿಂಗಲ್ ಇನ್ಸ್ಟ್ರಕ್ಷನ್, ಮಲ್ಟಿಪಲ್ ಡೇಟಾ) ಯ ಸಾರ. ಸಿಪಿಯು ಒಂದೇ ಸೂಚನೆಯನ್ನು ನೀಡುತ್ತದೆ, ಆದರೆ ಅದು ಒಂದು ವಿಶೇಷ, ಅಗಲವಾದ ರಿಜಿಸ್ಟರ್ನಲ್ಲಿ ಒಟ್ಟಿಗೆ ಪ್ಯಾಕ್ ಮಾಡಲಾದ ಬಹು ಡೇಟಾ ಪಾಯಿಂಟ್ಗಳ ಮೇಲೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ.
ಆಧುನಿಕ ಸಿಪಿಯುಗಳಲ್ಲಿ ಸಿಮ್ಡಿ ಹೇಗೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ
ಇಂಟೆಲ್ ಮತ್ತು ಎಎಮ್ಡಿಯಂತಹ ತಯಾರಕರ ಆಧುನಿಕ ಸಿಪಿಯುಗಳು ಈ ಸಮಾನಾಂತರ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು ನಿರ್ವಹಿಸಲು ವಿಶೇಷ ಸಿಮ್ಡಿ ರಿಜಿಸ್ಟರ್ಗಳು ಮತ್ತು ಇನ್ಸ್ಟ್ರಕ್ಷನ್ ಸೆಟ್ಗಳನ್ನು ಹೊಂದಿವೆ. ಈ ರಿಜಿಸ್ಟರ್ಗಳು ಸಾಮಾನ್ಯ ಉದ್ದೇಶದ ರಿಜಿಸ್ಟರ್ಗಳಿಗಿಂತ ಹೆಚ್ಚು ಅಗಲವಾಗಿರುತ್ತವೆ ಮತ್ತು ಒಂದೇ ಬಾರಿಗೆ ಅನೇಕ ಡೇಟಾ ಅಂಶಗಳನ್ನು ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳಬಲ್ಲವು.
- ಸಿಮ್ಡಿ ರಿಜಿಸ್ಟರ್ಗಳು: ಇವು ಸಿಪಿಯುನಲ್ಲಿರುವ ದೊಡ್ಡ ಹಾರ್ಡ್ವೇರ್ ರಿಜಿಸ್ಟರ್ಗಳಾಗಿವೆ. ಅವುಗಳ ಗಾತ್ರಗಳು ಕಾಲಾನಂತರದಲ್ಲಿ ವಿಕಸನಗೊಂಡಿವೆ: 128-ಬಿಟ್, 256-ಬಿಟ್, ಮತ್ತು ಈಗ 512-ಬಿಟ್ ರಿಜಿಸ್ಟರ್ಗಳು ಸಾಮಾನ್ಯವಾಗಿದೆ. ಉದಾಹರಣೆಗೆ, 256-ಬಿಟ್ ರಿಜಿಸ್ಟರ್ ಎಂಟು 32-ಬಿಟ್ ಫ್ಲೋಟಿಂಗ್-ಪಾಯಿಂಟ್ ಸಂಖ್ಯೆಗಳನ್ನು ಅಥವಾ ನಾಲ್ಕು 64-ಬಿಟ್ ಫ್ಲೋಟಿಂಗ್-ಪಾಯಿಂಟ್ ಸಂಖ್ಯೆಗಳನ್ನು ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳಬಹುದು.
- ಸಿಮ್ಡಿ ಇನ್ಸ್ಟ್ರಕ್ಷನ್ ಸೆಟ್ಗಳು: ಸಿಪಿಯುಗಳು ಈ ರಿಜಿಸ್ಟರ್ಗಳೊಂದಿಗೆ ಕೆಲಸ ಮಾಡಲು ನಿರ್ದಿಷ್ಟ ಸೂಚನೆಗಳನ್ನು ಹೊಂದಿವೆ. ನೀವು ಈ ಸಂಕ್ಷಿಪ್ತ ರೂಪಗಳನ್ನು ಕೇಳಿರಬಹುದು:
- ಎಸ್ಎಸ್ಇ (ಸ್ಟ್ರೀಮಿಂಗ್ ಸಿಮ್ಡಿ ಎಕ್ಸ್ಟೆನ್ಶನ್ಸ್): ಒಂದು ಹಳೆಯ 128-ಬಿಟ್ ಇನ್ಸ್ಟ್ರಕ್ಷನ್ ಸೆಟ್.
- ಎವಿಎಕ್ಸ್ (ಅಡ್ವಾನ್ಸ್ಡ್ ವೆಕ್ಟರ್ ಎಕ್ಸ್ಟೆನ್ಶನ್ಸ್): ಒಂದು 256-ಬಿಟ್ ಇನ್ಸ್ಟ್ರಕ್ಷನ್ ಸೆಟ್, ಇದು ಗಮನಾರ್ಹ ಕಾರ್ಯಕ್ಷಮತೆಯ ಹೆಚ್ಚಳವನ್ನು ನೀಡುತ್ತದೆ.
- ಎವಿಎಕ್ಸ್2: ಹೆಚ್ಚು ಸೂಚನೆಗಳೊಂದಿಗೆ ಎವಿಎಕ್ಸ್ನ ವಿಸ್ತರಣೆ.
- ಎವಿಎಕ್ಸ್-512: ಅನೇಕ ಆಧುನಿಕ ಸರ್ವರ್ ಮತ್ತು ಉನ್ನತ-ಮಟ್ಟದ ಡೆಸ್ಕ್ಟಾಪ್ ಸಿಪಿಯುಗಳಲ್ಲಿ ಕಂಡುಬರುವ ಒಂದು ಶಕ್ತಿಯುತ 512-ಬಿಟ್ ಇನ್ಸ್ಟ್ರಕ್ಷನ್ ಸೆಟ್.
ಇದನ್ನು ದೃಶ್ಯೀಕರಿಸೋಣ. ನಾವು ಎರಡು ಅರೇಗಳನ್ನು, `A = [1, 2, 3, 4]` ಮತ್ತು `B = [5, 6, 7, 8]` ಸೇರಿಸಲು ಬಯಸುತ್ತೇವೆ, ಇಲ್ಲಿ ಪ್ರತಿ ಸಂಖ್ಯೆಯು 32-ಬಿಟ್ ಪೂರ್ಣಾಂಕವಾಗಿದೆ. 128-ಬಿಟ್ ಸಿಮ್ಡಿ ರಿಜಿಸ್ಟರ್ಗಳಿರುವ ಸಿಪಿಯುನಲ್ಲಿ:
- ಸಿಪಿಯು `[1, 2, 3, 4]` ಅನ್ನು ಸಿಮ್ಡಿ ರಿಜಿಸ್ಟರ್ 1 ಗೆ ಲೋಡ್ ಮಾಡುತ್ತದೆ.
- ಸಿಪಿಯು `[5, 6, 7, 8]` ಅನ್ನು ಸಿಮ್ಡಿ ರಿಜಿಸ್ಟರ್ 2 ಗೆ ಲೋಡ್ ಮಾಡುತ್ತದೆ.
- ಸಿಪಿಯು ಒಂದೇ ವೆಕ್ಟರೈಸ್ಡ್ "add" ಸೂಚನೆಯನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸುತ್ತದೆ (`_mm_add_epi32` ಒಂದು ನೈಜ ಸೂಚನೆಯ ಉದಾಹರಣೆಯಾಗಿದೆ).
- ಒಂದೇ ಕ್ಲಾಕ್ ಸೈಕಲ್ನಲ್ಲಿ, ಹಾರ್ಡ್ವೇರ್ ನಾಲ್ಕು ಪ್ರತ್ಯೇಕ ಸಂಕಲನಗಳನ್ನು ಸಮಾನಾಂತರವಾಗಿ ನಿರ್ವಹಿಸುತ್ತದೆ: `1+5`, `2+6`, `3+7`, `4+8`.
- ಫಲಿತಾಂಶ, `[6, 8, 10, 12]`, ಮತ್ತೊಂದು ಸಿಮ್ಡಿ ರಿಜಿಸ್ಟರ್ನಲ್ಲಿ ಸಂಗ್ರಹವಾಗುತ್ತದೆ.
ಇದು ಕೋರ್ ಕಂಪ್ಯೂಟೇಶನ್ಗೆ ಎಸ್ಐಎಸ್ಡಿ ವಿಧಾನಕ್ಕಿಂತ 4 ಪಟ್ಟು ವೇಗವಾಗಿರುತ್ತದೆ, ಸೂಚನೆಗಳ ರವಾನೆ ಮತ್ತು ಲೂಪ್ ಓವರ್ಹೆಡ್ನಲ್ಲಿನ ಭಾರಿ ಇಳಿಕೆಯನ್ನು ಲೆಕ್ಕಿಸದೆಯೇ.
ಕಾರ್ಯಕ್ಷಮತೆಯ ಅಂತರ: ಸ್ಕೇಲಾರ್ ಮತ್ತು ವೆಕ್ಟರ್ ಕಾರ್ಯಾಚರಣೆಗಳು
ಸಾಂಪ್ರದಾಯಿಕ, ಒಂದು ಸಮಯದಲ್ಲಿ ಒಂದು ಅಂಶದ ಕಾರ್ಯಾಚರಣೆಗೆ ಸ್ಕೇಲಾರ್ ಕಾರ್ಯಾಚರಣೆ ಎಂದು ಕರೆಯಲಾಗುತ್ತದೆ. ಸಂಪೂರ್ಣ ಅರೇ ಅಥವಾ ಡೇಟಾ ವೆಕ್ಟರ್ನ ಮೇಲಿನ ಕಾರ್ಯಾಚರಣೆಯನ್ನು ವೆಕ್ಟರ್ ಕಾರ್ಯಾಚರಣೆ ಎಂದು ಕರೆಯಲಾಗುತ್ತದೆ. ಕಾರ್ಯಕ್ಷಮತೆಯ ವ್ಯತ್ಯಾಸವು ಸೂಕ್ಷ್ಮವಾಗಿಲ್ಲ; ಅದು ಹಲವು ಪಟ್ಟು ಹೆಚ್ಚಿರಬಹುದು.
- ಕಡಿಮೆ ಓವರ್ಹೆಡ್: ಪೈಥಾನ್ನಲ್ಲಿ, ಲೂಪ್ನ ಪ್ರತಿ ಪುನರಾವರ್ತನೆಯು ಓವರ್ಹೆಡ್ ಅನ್ನು ಒಳಗೊಂಡಿರುತ್ತದೆ: ಲೂಪ್ ಸ್ಥಿತಿಯನ್ನು ಪರಿಶೀಲಿಸುವುದು, ಕೌಂಟರ್ ಅನ್ನು ಹೆಚ್ಚಿಸುವುದು, ಮತ್ತು ಇಂಟರ್ಪ್ರಿಟರ್ ಮೂಲಕ ಕಾರ್ಯಾಚರಣೆಯನ್ನು ರವಾನಿಸುವುದು. ಒಂದೇ ವೆಕ್ಟರ್ ಕಾರ್ಯಾಚರಣೆಗೆ ಒಂದೇ ರವಾನೆ ಇರುತ್ತದೆ, ಅರೇಯಲ್ಲಿ ಸಾವಿರ ಅಥವಾ ಮಿಲಿಯನ್ ಅಂಶಗಳಿವೆಯೇ ಎಂಬುದನ್ನು ಲೆಕ್ಕಿಸದೆ.
- ಹಾರ್ಡ್ವೇರ್ ಸಮಾನಾಂತರತೆ: ನಾವು ನೋಡಿದಂತೆ, ಸಿಮ್ಡಿ ಒಂದೇ ಸಿಪಿಯು ಕೋರ್ನೊಳಗಿನ ಸಮಾನಾಂತರ ಸಂಸ್ಕರಣಾ ಘಟಕಗಳನ್ನು ನೇರವಾಗಿ ಬಳಸಿಕೊಳ್ಳುತ್ತದೆ.
- ಸುಧಾರಿತ ಕ್ಯಾಶ್ ಲೊಕ್ಯಾಲಿಟಿ: ವೆಕ್ಟರೈಸ್ಡ್ ಕಾರ್ಯಾಚರಣೆಗಳು ಸಾಮಾನ್ಯವಾಗಿ ಮೆಮೊರಿಯ ಸತತ ಬ್ಲಾಕ್ಗಳಿಂದ ಡೇಟಾವನ್ನು ಓದುತ್ತವೆ. ಇದು ಸಿಪಿಯುನ ಕ್ಯಾಶಿಂಗ್ ವ್ಯವಸ್ಥೆಗೆ ಅತ್ಯಂತ ದಕ್ಷವಾಗಿರುತ್ತದೆ, ಇದು ಅನುಕ್ರಮ ತುಣುಕುಗಳಲ್ಲಿ ಡೇಟಾವನ್ನು ಪೂರ್ವ-ಪಡೆಯಲು ವಿನ್ಯಾಸಗೊಳಿಸಲಾಗಿದೆ. ಲೂಪ್ಗಳಲ್ಲಿನ ಯಾದೃಚ್ಛಿಕ ಪ್ರವೇಶ ಮಾದರಿಗಳು ಆಗಾಗ್ಗೆ "ಕ್ಯಾಶ್ ಮಿಸ್ಸ್" ಗೆ ಕಾರಣವಾಗಬಹುದು, ಅದು ನಂಬಲಾಗದಷ್ಟು ನಿಧಾನವಾಗಿರುತ್ತದೆ.
ಪೈಥಾನಿಕ್ ವಿಧಾನ: ನಂಪೈ (NumPy) ಯೊಂದಿಗೆ ವೆಕ್ಟರೈಸೇಶನ್
ಹಾರ್ಡ್ವೇರ್ ಅನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವುದು ಆಕರ್ಷಕವಾಗಿದೆ, ಆದರೆ ಅದರ ಶಕ್ತಿಯನ್ನು ಬಳಸಿಕೊಳ್ಳಲು ನೀವು ಕೆಳಮಟ್ಟದ ಅಸೆಂಬ್ಲಿ ಕೋಡ್ ಬರೆಯುವ ಅಗತ್ಯವಿಲ್ಲ. ಪೈಥಾನ್ ಪರಿಸರ ವ್ಯವಸ್ಥೆಯು ವೆಕ್ಟರೈಸೇಶನ್ ಅನ್ನು ಸುಲಭ ಮತ್ತು ಅರ್ಥಗರ್ಭಿತವಾಗಿಸುವ ಒಂದು ಅದ್ಭುತ ಲೈಬ್ರರಿಯನ್ನು ಹೊಂದಿದೆ: ನಂಪೈ (NumPy).
ನಂಪೈ: ಪೈಥಾನ್ನಲ್ಲಿ ವೈಜ್ಞಾನಿಕ ಕಂಪ್ಯೂಟಿಂಗ್ನ ಅಡಿಪಾಯ
ನಂಪೈ ಪೈಥಾನ್ನಲ್ಲಿ ಸಂಖ್ಯಾತ್ಮಕ ಗಣನೆಗೆ ಮೂಲಭೂತ ಪ್ಯಾಕೇಜ್ ಆಗಿದೆ. ಅದರ ಮುಖ್ಯ ವೈಶಿಷ್ಟ್ಯವೆಂದರೆ ಶಕ್ತಿಯುತ ಎನ್-ಡೈಮೆನ್ಷನಲ್ ಅರೇ ಆಬ್ಜೆಕ್ಟ್, `ndarray`. ನಂಪೈನ ನಿಜವಾದ ಮ್ಯಾಜಿಕ್ ಏನೆಂದರೆ, ಅದರ ಅತ್ಯಂತ ನಿರ್ಣಾಯಕ ದಿನಚರಿಗಳು (ಗಣಿತದ ಕಾರ್ಯಾಚರಣೆಗಳು, ಅರೇ ಮ್ಯಾನಿಪ್ಯುಲೇಶನ್, ಇತ್ಯಾದಿ) ಪೈಥಾನ್ನಲ್ಲಿ ಬರೆಯಲ್ಪಟ್ಟಿಲ್ಲ. ಅವುಗಳು ಹೆಚ್ಚು ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾದ, ಪೂರ್ವ-ಸಂಕಲಿತ ಸಿ ಅಥವಾ ಫೋರ್ಟ್ರಾನ್ ಕೋಡ್ ಆಗಿದ್ದು, ಅವು BLAS (ಬೇಸಿಕ್ ಲೀನಿಯರ್ ಆಲ್ಜಿಬ್ರಾ ಸಬ್ಪ್ರೋಗ್ರಾಮ್ಗಳು) ಮತ್ತು LAPACK (ಲೀನಿಯರ್ ಆಲ್ಜಿಬ್ರಾ ಪ್ಯಾಕೇಜ್) ನಂತಹ ಕೆಳಮಟ್ಟದ ಲೈಬ್ರರಿಗಳ ವಿರುದ್ಧ ಲಿಂಕ್ ಮಾಡಲಾಗಿದೆ. ಈ ಲೈಬ್ರರಿಗಳು ಹೋಸ್ಟ್ ಸಿಪಿಯುನಲ್ಲಿ ಲಭ್ಯವಿರುವ ಸಿಮ್ಡಿ ಇನ್ಸ್ಟ್ರಕ್ಷನ್ ಸೆಟ್ಗಳ ಅತ್ಯುತ್ತಮ ಬಳಕೆಯನ್ನು ಮಾಡಲು ಮಾರಾಟಗಾರರಿಂದ ಟ್ಯೂನ್ ಮಾಡಲ್ಪಟ್ಟಿರುತ್ತವೆ.
ನೀವು ನಂಪೈನಲ್ಲಿ `C = A + B` ಎಂದು ಬರೆದಾಗ, ನೀವು ಪೈಥಾನ್ ಲೂಪ್ ಅನ್ನು ಚಲಾಯಿಸುತ್ತಿಲ್ಲ. ನೀವು ಸಿಮ್ಡಿ ಸೂಚನೆಗಳನ್ನು ಬಳಸಿ ಸಂಕಲನವನ್ನು ನಿರ್ವಹಿಸುವ ಹೆಚ್ಚು ಆಪ್ಟಿಮೈಸ್ ಮಾಡಿದ ಸಿ ಫಂಕ್ಷನ್ಗೆ ಒಂದೇ ಆಜ್ಞೆಯನ್ನು ರವಾನಿಸುತ್ತಿದ್ದೀರಿ.
ಪ್ರಾಯೋಗಿಕ ಉದಾಹರಣೆ: ಪೈಥಾನ್ ಲೂಪ್ನಿಂದ ನಂಪೈ ಅರೇಗೆ
ಇದನ್ನು ಕಾರ್ಯರೂಪದಲ್ಲಿ ನೋಡೋಣ. ನಾವು ಎರಡು ದೊಡ್ಡ ಸಂಖ್ಯೆಗಳ ಅರೇಗಳನ್ನು ಸೇರಿಸೋಣ, ಮೊದಲು ಶುದ್ಧ ಪೈಥಾನ್ ಲೂಪ್ನೊಂದಿಗೆ ಮತ್ತು ನಂತರ ನಂಪೈಯೊಂದಿಗೆ. ನಿಮ್ಮ ಸ್ವಂತ ಯಂತ್ರದಲ್ಲಿ ಫಲಿತಾಂಶಗಳನ್ನು ನೋಡಲು ನೀವು ಈ ಕೋಡ್ ಅನ್ನು ಜೂಪಿಟರ್ ನೋಟ್ಬುಕ್ ಅಥವಾ ಪೈಥಾನ್ ಸ್ಕ್ರಿಪ್ಟ್ನಲ್ಲಿ ಚಲಾಯಿಸಬಹುದು.
ಮೊದಲು, ನಾವು ಡೇಟಾವನ್ನು ಸಿದ್ಧಪಡಿಸೋಣ:
import time
import numpy as np
# ನಾವು ದೊಡ್ಡ ಸಂಖ್ಯೆಯ ಅಂಶಗಳನ್ನು ಬಳಸೋಣ
num_elements = 10_000_000
# ಶುದ್ಧ ಪೈಥಾನ್ ಪಟ್ಟಿಗಳು
list_a = [i * 0.5 for i in range(num_elements)]
list_b = [i * 0.2 for i in range(num_elements)]
# ನಂಪೈ ಅರೇಗಳು
array_a = np.arange(num_elements) * 0.5
array_b = np.arange(num_elements) * 0.2
ಈಗ, ಶುದ್ಧ ಪೈಥಾನ್ ಲೂಪ್ನ ಸಮಯವನ್ನು ಅಳೆಯೋಣ:
start_time = time.time()
result_list = [0] * num_elements
for i in range(num_elements):
result_list[i] = list_a[i] + list_b[i]
end_time = time.time()
python_duration = end_time - start_time
print(f"ಶುದ್ಧ ಪೈಥಾನ್ ಲೂಪ್ ತೆಗೆದುಕೊಂಡ ಸಮಯ: {python_duration:.6f} ಸೆಕೆಂಡುಗಳು")
ಮತ್ತು ಈಗ, ಸಮಾನವಾದ ನಂಪೈ ಕಾರ್ಯಾಚರಣೆ:
start_time = time.time()
result_array = array_a + array_b
end_time = time.time()
numpy_duration = end_time - start_time
print(f"ನಂಪೈ ವೆಕ್ಟರೈಸ್ಡ್ ಕಾರ್ಯಾಚರಣೆ ತೆಗೆದುಕೊಂಡ ಸಮಯ: {numpy_duration:.6f} ಸೆಕೆಂಡುಗಳು")
# ವೇಗವರ್ಧನೆಯನ್ನು ಲೆಕ್ಕಾಚಾರ ಮಾಡಿ
if numpy_duration > 0:
print(f"ನಂಪೈ ಅಂದಾಜು {python_duration / numpy_duration:.2f}x ವೇಗವಾಗಿದೆ.")
ಒಂದು ಸಾಮಾನ್ಯ ಆಧುನಿಕ ಯಂತ್ರದಲ್ಲಿ, ಫಲಿತಾಂಶವು ಬೆರಗುಗೊಳಿಸುವಂತಿರುತ್ತದೆ. ನಂಪೈ ಆವೃತ್ತಿಯು 50 ರಿಂದ 200 ಪಟ್ಟು ವೇಗವಾಗಿರಬಹುದೆಂದು ನೀವು ನಿರೀಕ್ಷಿಸಬಹುದು. ಇದು ಸಣ್ಣ ಆಪ್ಟಿಮೈಸೇಶನ್ ಅಲ್ಲ; ಇದು ಗಣನೆಯನ್ನು ಹೇಗೆ ನಿರ್ವಹಿಸಲಾಗುತ್ತದೆ ಎಂಬುದರಲ್ಲಿ ಒಂದು ಮೂಲಭೂತ ಬದಲಾವಣೆಯಾಗಿದೆ.
ಯುನಿವರ್ಸಲ್ ಫಂಕ್ಷನ್ಸ್ (ufuncs): ನಂಪೈ ವೇಗದ ಹಿಂದಿನ ಇಂಜಿನ್
ನಾವು ಇದೀಗ ನಿರ್ವಹಿಸಿದ ಕಾರ್ಯಾಚರಣೆ (`+`) ಯು ನಂಪೈ ಯುನಿವರ್ಸಲ್ ಫಂಕ್ಷನ್, ಅಥವಾ ufunc ನ ಉದಾಹರಣೆಯಾಗಿದೆ. ಇವು `ndarray` ಗಳ ಮೇಲೆ ಅಂಶ-ಪ್ರತಿ-ಅಂಶದ ರೀತಿಯಲ್ಲಿ ಕಾರ್ಯನಿರ್ವಹಿಸುವ ಫಂಕ್ಷನ್ಗಳಾಗಿವೆ. ಇವು ನಂಪೈನ ವೆಕ್ಟರೈಸ್ಡ್ ಶಕ್ತಿಯ ತಿರುಳು.
ufuncs ನ ಉದಾಹರಣೆಗಳು:
- ಗಣಿತದ ಕಾರ್ಯಾಚರಣೆಗಳು: `np.add`, `np.subtract`, `np.multiply`, `np.divide`, `np.power`.
- ತ್ರಿಕೋನಮಿತಿಯ ಫಂಕ್ಷನ್ಗಳು: `np.sin`, `np.cos`, `np.tan`.
- ತಾರ್ಕಿಕ ಕಾರ್ಯಾಚರಣೆಗಳು: `np.logical_and`, `np.logical_or`, `np.greater`.
- ಘಾತೀಯ ಮತ್ತು ಲಾಗರಿದಮಿಕ್ ಫಂಕ್ಷನ್ಗಳು: `np.exp`, `np.log`.
ಸ್ಪಷ್ಟವಾದ ಲೂಪ್ ಬರೆಯದೆಯೇ ಸಂಕೀರ್ಣ ಸೂತ್ರಗಳನ್ನು ವ್ಯಕ್ತಪಡಿಸಲು ನೀವು ಈ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು ಒಟ್ಟಿಗೆ ಜೋಡಿಸಬಹುದು. ಗಾಸಿಯನ್ ಫಂಕ್ಷನ್ ಅನ್ನು ಲೆಕ್ಕಾಚಾರ ಮಾಡುವುದನ್ನು ಪರಿಗಣಿಸಿ:
# x ಎಂಬುದು ಮಿಲಿಯನ್ ಪಾಯಿಂಟ್ಗಳಿರುವ ನಂಪೈ ಅರೇ
x = np.linspace(-5, 5, 1_000_000)
# ಸ್ಕೇಲಾರ್ ವಿಧಾನ (ಬಹಳ ನಿಧಾನ)
result = []
for val in x:
term = -0.5 * (val ** 2)
result.append((1 / np.sqrt(2 * np.pi)) * np.exp(term))
# ವೆಕ್ಟರೈಸ್ಡ್ ನಂಪೈ ವಿಧಾನ (ಅತ್ಯಂತ ವೇಗ)
result_vectorized = (1 / np.sqrt(2 * np.pi)) * np.exp(-0.5 * x**2)
ವೆಕ್ಟರೈಸ್ಡ್ ಆವೃತ್ತಿಯು ನಾಟಕೀಯವಾಗಿ ವೇಗವಾಗಿರುವುದಲ್ಲದೆ, ಸಂಖ್ಯಾತ್ಮಕ ಕಂಪ್ಯೂಟಿಂಗ್ನ ಪರಿಚಯವಿರುವವರಿಗೆ ಹೆಚ್ಚು ಸಂಕ್ಷಿಪ್ತ ಮತ್ತು ಓದಲು ಸುಲಭವಾಗಿದೆ.
ಮೂಲಭೂತ ಅಂಶಗಳನ್ನು ಮೀರಿ: ಬ್ರಾಡ್ಕಾಸ್ಟಿಂಗ್ ಮತ್ತು ಮೆಮೊರಿ ಲೇಔಟ್
ನಂಪೈನ ವೆಕ್ಟರೈಸೇಶನ್ ಸಾಮರ್ಥ್ಯಗಳನ್ನು ಬ್ರಾಡ್ಕಾಸ್ಟಿಂಗ್ ಎಂಬ ಪರಿಕಲ್ಪನೆಯಿಂದ ಮತ್ತಷ್ಟು ಹೆಚ್ಚಿಸಲಾಗಿದೆ. ಅಂಕಗಣಿತದ ಕಾರ್ಯಾಚರಣೆಗಳ ಸಮಯದಲ್ಲಿ ನಂಪೈ ವಿಭಿನ್ನ ಆಕಾರಗಳ ಅರೇಗಳನ್ನು ಹೇಗೆ ಪರಿಗಣಿಸುತ್ತದೆ ಎಂಬುದನ್ನು ಇದು ವಿವರಿಸುತ್ತದೆ. ಬ್ರಾಡ್ಕಾಸ್ಟಿಂಗ್ ದೊಡ್ಡ ಅರೇ ಮತ್ತು ಸಣ್ಣ ಅರೇ (ಉದಾ., ಒಂದು ಸ್ಕೇಲಾರ್) ನಡುವೆ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು ನಿರ್ವಹಿಸಲು ನಿಮಗೆ ಅನುವು ಮಾಡಿಕೊಡುತ್ತದೆ, ಸಣ್ಣ ಅರೇಯ ನಕಲುಗಳನ್ನು ದೊಡ್ಡದರ ಆಕಾರಕ್ಕೆ ಹೊಂದಿಸಲು ಸ್ಪಷ್ಟವಾಗಿ ರಚಿಸದೆಯೇ. ಇದು ಮೆಮೊರಿಯನ್ನು ಉಳಿಸುತ್ತದೆ ಮತ್ತು ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ಸುಧಾರಿಸುತ್ತದೆ.
ಉದಾಹರಣೆಗೆ, ಒಂದು ಅರೇಯಲ್ಲಿನ ಪ್ರತಿ ಅಂಶವನ್ನು 10 ರ ಅಂಶದಿಂದ ಅಳೆಯಲು, ನೀವು 10 ಗಳಿಂದ ತುಂಬಿದ ಅರೇಯನ್ನು ರಚಿಸುವ ಅಗತ್ಯವಿಲ್ಲ. ನೀವು ಸರಳವಾಗಿ ಬರೆಯುತ್ತೀರಿ:
my_array = np.array([1, 2, 3, 4])
scaled_array = my_array * 10 # my_array ಅಡ್ಡಲಾಗಿ ಸ್ಕೇಲಾರ್ 10 ಅನ್ನು ಬ್ರಾಡ್ಕಾಸ್ಟಿಂಗ್ ಮಾಡುವುದು
ಇದಲ್ಲದೆ, ಮೆಮೊರಿಯಲ್ಲಿ ಡೇಟಾವನ್ನು ಹೇಗೆ ಜೋಡಿಸಲಾಗಿದೆ ಎಂಬುದು ನಿರ್ಣಾಯಕವಾಗಿದೆ. ನಂಪೈ ಅರೇಗಳನ್ನು ಮೆಮೊರಿಯ ಒಂದು ಸತತ ಬ್ಲಾಕ್ನಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾಗುತ್ತದೆ. ಇದು ಸಿಮ್ಡಿಗೆ ಅತ್ಯಗತ್ಯ, ಏಕೆಂದರೆ ಇದಕ್ಕೆ ಡೇಟಾವನ್ನು ಅದರ ಅಗಲವಾದ ರಿಜಿಸ್ಟರ್ಗಳಿಗೆ ಅನುಕ್ರಮವಾಗಿ ಲೋಡ್ ಮಾಡಬೇಕಾಗುತ್ತದೆ. ಮೆಮೊರಿ ಲೇಔಟ್ ಅನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವುದು (ಉದಾ., ಸಿ-ಶೈಲಿಯ ರೋ-ಮೇಜರ್ ಮತ್ತು ಫೋರ್ಟ್ರಾನ್-ಶೈಲಿಯ ಕಾಲಮ್-ಮೇಜರ್) ಸುಧಾರಿತ ಕಾರ್ಯಕ್ಷಮತೆ ಟ್ಯೂನಿಂಗ್ಗೆ ಮುಖ್ಯವಾಗುತ್ತದೆ, ವಿಶೇಷವಾಗಿ ಬಹು-ಆಯಾಮದ ಡೇಟಾದೊಂದಿಗೆ ಕೆಲಸ ಮಾಡುವಾಗ.
ಗಡಿಗಳನ್ನು ಮೀರಿ: ಸುಧಾರಿತ ಸಿಮ್ಡಿ ಲೈಬ್ರರಿಗಳು
ಪೈಥಾನ್ನಲ್ಲಿ ವೆಕ್ಟರೈಸೇಶನ್ಗೆ ನಂಪೈ ಮೊದಲ ಮತ್ತು ಪ್ರಮುಖ ಸಾಧನವಾಗಿದೆ. ಆದಾಗ್ಯೂ, ನಿಮ್ಮ ಅಲ್ಗಾರಿದಮ್ ಅನ್ನು ಪ್ರಮಾಣಿತ ನಂಪೈ ufuncs ಬಳಸಿ ಸುಲಭವಾಗಿ ವ್ಯಕ್ತಪಡಿಸಲು ಸಾಧ್ಯವಾಗದಿದ್ದಾಗ ಏನಾಗುತ್ತದೆ? ಬಹುಶಃ ನೀವು ಸಂಕೀರ್ಣ ಷರತ್ತುಬದ್ಧ ತರ್ಕವನ್ನು ಹೊಂದಿರುವ ಲೂಪ್ ಅನ್ನು ಹೊಂದಿದ್ದೀರಿ ಅಥವಾ ಯಾವುದೇ ಲೈಬ್ರರಿಯಲ್ಲಿ ಲಭ್ಯವಿಲ್ಲದ ಕಸ್ಟಮ್ ಅಲ್ಗಾರಿದಮ್ ಅನ್ನು ಹೊಂದಿದ್ದೀರಿ. ಇಲ್ಲಿಯೇ ಹೆಚ್ಚು ಸುಧಾರಿತ ಉಪಕರಣಗಳು ಕಾರ್ಯರೂಪಕ್ಕೆ ಬರುತ್ತವೆ.
ನಂಬಾ (Numba): ವೇಗಕ್ಕಾಗಿ ಜಸ್ಟ್-ಇನ್-ಟೈಮ್ (JIT) ಕಂಪೈಲೇಶನ್
ನಂಬಾ ಒಂದು ಗಮನಾರ್ಹ ಲೈಬ್ರರಿಯಾಗಿದ್ದು ಅದು ಜಸ್ಟ್-ಇನ್-ಟೈಮ್ (JIT) ಕಂಪೈಲರ್ ಆಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ. ಇದು ನಿಮ್ಮ ಪೈಥಾನ್ ಕೋಡ್ ಅನ್ನು ಓದುತ್ತದೆ, ಮತ್ತು ರನ್ಟೈಮ್ನಲ್ಲಿ, ನೀವು ಪೈಥಾನ್ ಪರಿಸರವನ್ನು ಬಿಡದೆಯೇ ಅದನ್ನು ಹೆಚ್ಚು ಆಪ್ಟಿಮೈಸ್ ಮಾಡಿದ ಮಷೀನ್ ಕೋಡ್ಗೆ ಭಾಷಾಂತರಿಸುತ್ತದೆ. ಇದು ಲೂಪ್ಗಳನ್ನು ಆಪ್ಟಿಮೈಸ್ ಮಾಡುವುದರಲ್ಲಿ ವಿಶೇಷವಾಗಿ ಅದ್ಭುತವಾಗಿದೆ, ಇದು ಪ್ರಮಾಣಿತ ಪೈಥಾನ್ನ ಪ್ರಾಥಮಿಕ ದೌರ್ಬಲ್ಯವಾಗಿದೆ.
ನಂಬಾವನ್ನು ಬಳಸುವ ಅತ್ಯಂತ ಸಾಮಾನ್ಯ ವಿಧಾನವೆಂದರೆ ಅದರ ಡೆಕೋರೇಟರ್, `@jit`. ನಂಪೈನಲ್ಲಿ ವೆಕ್ಟರೈಸ್ ಮಾಡಲು ಕಷ್ಟಕರವಾದ ಉದಾಹರಣೆಯನ್ನು ತೆಗೆದುಕೊಳ್ಳೋಣ: ಕಸ್ಟಮ್ ಸಿಮ್ಯುಲೇಶನ್ ಲೂಪ್.
import numpy as np
from numba import jit
# ನಂಪೈನಲ್ಲಿ ವೆಕ್ಟರೈಸ್ ಮಾಡಲು ಕಷ್ಟಕರವಾದ ಒಂದು ಕಾಲ್ಪನಿಕ ಫಂಕ್ಷನ್
def simulate_particles_python(positions, velocities, steps):
for _ in range(steps):
for i in range(len(positions)):
# ಕೆಲವು ಸಂಕೀರ್ಣ, ಡೇಟಾ-ಅವಲಂಬಿತ ತರ್ಕ
if positions[i] > 0:
velocities[i] -= 9.8 * 0.01
else:
velocities[i] = -velocities[i] * 0.9 # ಅಸ್ಥಿತಿಸ್ಥಾಪಕ ಘರ್ಷಣೆ
positions[i] += velocities[i] * 0.01
return positions
# ಅದೇ ಫಂಕ್ಷನ್, ಆದರೆ ನಂಬಾ JIT ಡೆಕೋರೇಟರ್ನೊಂದಿಗೆ
@jit(nopython=True, fastmath=True)
def simulate_particles_numba(positions, velocities, steps):
for _ in range(steps):
for i in range(len(positions)):
if positions[i] > 0:
velocities[i] -= 9.8 * 0.01
else:
velocities[i] = -velocities[i] * 0.9
positions[i] += velocities[i] * 0.01
return positions
ಕೇವಲ `@jit(nopython=True)` ಡೆಕೋರೇಟರ್ ಅನ್ನು ಸೇರಿಸುವ ಮೂಲಕ, ನೀವು ನಂಬಾಗೆ ಈ ಫಂಕ್ಷನ್ ಅನ್ನು ಮಷೀನ್ ಕೋಡ್ಗೆ ಕಂಪೈಲ್ ಮಾಡಲು ಹೇಳುತ್ತಿದ್ದೀರಿ. `nopython=True` ಆರ್ಗ್ಯುಮೆಂಟ್ ನಿರ್ಣಾಯಕವಾಗಿದೆ; ಇದು ನಂಬಾ ನಿಧಾನಗತಿಯ ಪೈಥಾನ್ ಇಂಟರ್ಪ್ರಿಟರ್ಗೆ ಹಿಂತಿರುಗದ ಕೋಡ್ ಅನ್ನು ಉತ್ಪಾದಿಸುತ್ತದೆ ಎಂದು ಖಚಿತಪಡಿಸುತ್ತದೆ. `fastmath=True` ಫ್ಲ್ಯಾಗ್ ನಂಬಾಗೆ ಕಡಿಮೆ ನಿಖರವಾದ ಆದರೆ ವೇಗವಾದ ಗಣಿತದ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು ಬಳಸಲು ಅನುಮತಿಸುತ್ತದೆ, ಇದು ಸ್ವಯಂ-ವೆಕ್ಟರೈಸೇಶನ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಬಹುದು. ನಂಬಾದ ಕಂಪೈಲರ್ ಆಂತರಿಕ ಲೂಪ್ ಅನ್ನು ವಿಶ್ಲೇಷಿಸಿದಾಗ, ಅದು ಷರತ್ತುಬದ್ಧ ತರ್ಕದೊಂದಿಗೆ ಸಹ, ಒಂದೇ ಬಾರಿಗೆ ಅನೇಕ ಕಣಗಳನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಸಿಮ್ಡಿ ಸೂಚನೆಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಉತ್ಪಾದಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತದೆ, ಇದು ಕೈಯಿಂದ ಬರೆದ ಸಿ ಕೋಡ್ನ ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ಸರಿಗಟ್ಟುತ್ತದೆ ಅಥವಾ ಮೀರಿಸುತ್ತದೆ.
ಸೈಥಾನ್ (Cython): ಪೈಥಾನ್ ಅನ್ನು ಸಿ/ಸಿ++ ನೊಂದಿಗೆ ಸಂಯೋಜಿಸುವುದು
ನಂಬಾ ಜನಪ್ರಿಯವಾಗುವ ಮೊದಲು, ಸೈಥಾನ್ ಪೈಥಾನ್ ಕೋಡ್ ಅನ್ನು ವೇಗಗೊಳಿಸಲು ಪ್ರಾಥಮಿಕ ಸಾಧನವಾಗಿತ್ತು. ಸೈಥಾನ್ ಪೈಥಾನ್ ಭಾಷೆಯ ಒಂದು ಸೂಪರ್ಸೆಟ್ ಆಗಿದ್ದು, ಇದು ಸಿ/ಸಿ++ ಫಂಕ್ಷನ್ಗಳನ್ನು ಕರೆಯುವುದನ್ನು ಮತ್ತು ವೇರಿಯೇಬಲ್ಗಳು ಮತ್ತು ಕ್ಲಾಸ್ ಗುಣಲಕ್ಷಣಗಳ ಮೇಲೆ ಸಿ ಪ್ರಕಾರಗಳನ್ನು ಘೋಷಿಸುವುದನ್ನು ಸಹ ಬೆಂಬಲಿಸುತ್ತದೆ. ಇದು ಅಹೆಡ್-ಆಫ್-ಟೈಮ್ (AOT) ಕಂಪೈಲರ್ ಆಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ. ನೀವು ನಿಮ್ಮ ಕೋಡ್ ಅನ್ನು `.pyx` ಫೈಲ್ನಲ್ಲಿ ಬರೆಯುತ್ತೀರಿ, ಅದನ್ನು ಸೈಥಾನ್ ಸಿ/ಸಿ++ ಸೋರ್ಸ್ ಫೈಲ್ಗೆ ಕಂಪೈಲ್ ಮಾಡುತ್ತದೆ, ನಂತರ ಅದನ್ನು ಪ್ರಮಾಣಿತ ಪೈಥಾನ್ ವಿಸ್ತರಣೆ ಮಾಡ್ಯೂಲ್ಗೆ ಕಂಪೈಲ್ ಮಾಡಲಾಗುತ್ತದೆ.
ಸೈಥಾನ್ನ ಮುಖ್ಯ ಅನುಕೂಲವೆಂದರೆ ಅದು ಒದಗಿಸುವ ಸೂಕ್ಷ್ಮ-ಹಂತದ ನಿಯಂತ್ರಣ. ಸ್ಥಿರ ಪ್ರಕಾರದ ಘೋಷಣೆಗಳನ್ನು ಸೇರಿಸುವ ಮೂಲಕ, ನೀವು ಪೈಥಾನ್ನ ಡೈನಾಮಿಕ್ ಓವರ್ಹೆಡ್ನ ಹೆಚ್ಚಿನ ಭಾಗವನ್ನು ತೆಗೆದುಹಾಕಬಹುದು.
ಒಂದು ಸರಳ ಸೈಥಾನ್ ಫಂಕ್ಷನ್ ಹೀಗಿರಬಹುದು:
# 'sum_module.pyx' ಎಂಬ ಫೈಲ್ನಲ್ಲಿ
def sum_typed(long[:] arr):
cdef long total = 0
cdef int i
for i in range(arr.shape[0]):
total += arr[i]
return total
ಇಲ್ಲಿ, ಸಿ-ಮಟ್ಟದ ವೇರಿಯೇಬಲ್ಗಳನ್ನು (`total`, `i`) ಘೋಷಿಸಲು `cdef` ಅನ್ನು ಬಳಸಲಾಗುತ್ತದೆ, ಮತ್ತು `long[:]` ಇನ್ಪುಟ್ ಅರೇಯ ಟೈಪ್ಡ್ ಮೆಮೊರಿ ವ್ಯೂವನ್ನು ಒದಗಿಸುತ್ತದೆ. ಇದು ಸೈಥಾನ್ಗೆ ಹೆಚ್ಚು ದಕ್ಷವಾದ ಸಿ ಲೂಪ್ ಅನ್ನು ಉತ್ಪಾದಿಸಲು ಅನುವು ಮಾಡಿಕೊಡುತ್ತದೆ. ತಜ್ಞರಿಗೆ, ಸೈಥಾನ್ ಸಿಮ್ಡಿ ಇಂಟ್ರಿನ್ಸಿಕ್ಗಳನ್ನು ನೇರವಾಗಿ ಕರೆಯಲು ಯಾಂತ್ರಿಕ ವ್ಯವಸ್ಥೆಗಳನ್ನು ಸಹ ಒದಗಿಸುತ್ತದೆ, ಇದು ಕಾರ್ಯಕ್ಷಮತೆ-ನಿರ್ಣಾಯಕ ಅಪ್ಲಿಕೇಶನ್ಗಳಿಗೆ ಅಂತಿಮ ಹಂತದ ನಿಯಂತ್ರಣವನ್ನು ನೀಡುತ್ತದೆ.
ವಿಶೇಷ ಲೈಬ್ರರಿಗಳು: ಪರಿಸರ ವ್ಯವಸ್ಥೆಯ ಒಂದು ನೋಟ
ಉನ್ನತ-ಕಾರ್ಯಕ್ಷಮತೆಯ ಪೈಥಾನ್ ಪರಿಸರ ವ್ಯವಸ್ಥೆಯು ವಿಶಾಲವಾಗಿದೆ. ನಂಪೈ, ನಂಬಾ, ಮತ್ತು ಸೈಥಾನ್ನ ಹೊರತಾಗಿ, ಇತರ ವಿಶೇಷ ಉಪಕರಣಗಳು ಅಸ್ತಿತ್ವದಲ್ಲಿವೆ:
- NumExpr: ಒಂದು ವೇಗದ ಸಂಖ್ಯಾತ್ಮಕ ಅಭಿವ್ಯಕ್ತಿ ಮೌಲ್ಯಮಾಪಕ, ಇದು ಕೆಲವೊಮ್ಮೆ ಮೆಮೊರಿ ಬಳಕೆಯನ್ನು ಆಪ್ಟಿಮೈಸ್ ಮಾಡುವ ಮೂಲಕ ಮತ್ತು `2*a + 3*b` ನಂತಹ ಅಭಿವ್ಯಕ್ತಿಗಳನ್ನು ಮೌಲ್ಯಮಾಪನ ಮಾಡಲು ಬಹು ಕೋರ್ಗಳನ್ನು ಬಳಸುವ ಮೂಲಕ ನಂಪೈಗಿಂತ ಉತ್ತಮವಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ.
- Pythran: ಪೈಥಾನ್ ಕೋಡ್ನ ಉಪವಿಭಾಗವನ್ನು, ವಿಶೇಷವಾಗಿ ನಂಪೈ ಬಳಸುವ ಕೋಡ್ ಅನ್ನು, ಹೆಚ್ಚು ಆಪ್ಟಿಮೈಸ್ ಮಾಡಿದ ಸಿ++11 ಗೆ ಭಾಷಾಂತರಿಸುವ ಅಹೆಡ್-ಆಫ್-ಟೈಮ್ (AOT) ಕಂಪೈಲರ್, ಇದು ಆಗಾಗ್ಗೆ ಆಕ್ರಮಣಕಾರಿ ಸಿಮ್ಡಿ ವೆಕ್ಟರೈಸೇಶನ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ.
- Taichi: ಉನ್ನತ-ಕಾರ್ಯಕ್ಷಮತೆಯ ಸಮಾನಾಂತರ ಕಂಪ್ಯೂಟಿಂಗ್ಗಾಗಿ ಪೈಥಾನ್ನಲ್ಲಿ ಎಂಬೆಡ್ ಮಾಡಲಾದ ಡೊಮೇನ್-ನಿರ್ದಿಷ್ಟ ಭಾಷೆ (DSL), ವಿಶೇಷವಾಗಿ ಕಂಪ್ಯೂಟರ್ ಗ್ರಾಫಿಕ್ಸ್ ಮತ್ತು ಭೌತಶಾಸ್ತ್ರದ ಸಿಮ್ಯುಲೇಶನ್ಗಳಲ್ಲಿ ಜನಪ್ರಿಯವಾಗಿದೆ.
ಜಾಗತಿಕ ಪ್ರೇಕ್ಷಕರಿಗೆ ಪ್ರಾಯೋಗಿಕ ಪರಿಗಣನೆಗಳು ಮತ್ತು ಉತ್ತಮ ಅಭ್ಯಾಸಗಳು
ಉನ್ನತ-ಕಾರ್ಯಕ್ಷಮತೆಯ ಕೋಡ್ ಬರೆಯುವುದು ಕೇವಲ ಸರಿಯಾದ ಲೈಬ್ರರಿಯನ್ನು ಬಳಸುವುದಕ್ಕಿಂತ ಹೆಚ್ಚಿನದನ್ನು ಒಳಗೊಂಡಿರುತ್ತದೆ. ಇಲ್ಲಿ ಕೆಲವು ಸಾರ್ವತ್ರಿಕವಾಗಿ ಅನ್ವಯವಾಗುವ ಉತ್ತಮ ಅಭ್ಯಾಸಗಳಿವೆ.
ಸಿಮ್ಡಿ ಬೆಂಬಲವನ್ನು ಹೇಗೆ ಪರಿಶೀಲಿಸುವುದು
ನೀವು ಪಡೆಯುವ ಕಾರ್ಯಕ್ಷಮತೆಯು ನಿಮ್ಮ ಕೋಡ್ ಚಾಲನೆಯಲ್ಲಿರುವ ಹಾರ್ಡ್ವೇರ್ ಅನ್ನು ಅವಲಂಬಿಸಿರುತ್ತದೆ. ನಿರ್ದಿಷ್ಟ ಸಿಪಿಯು ಯಾವ ಸಿಮ್ಡಿ ಇನ್ಸ್ಟ್ರಕ್ಷನ್ ಸೆಟ್ಗಳನ್ನು ಬೆಂಬಲಿಸುತ್ತದೆ ಎಂಬುದನ್ನು ತಿಳಿದುಕೊಳ್ಳುವುದು ಉಪಯುಕ್ತವಾಗಿದೆ. ನೀವು `py-cpuinfo` ನಂತಹ ಕ್ರಾಸ್-ಪ್ಲಾಟ್ಫಾರ್ಮ್ ಲೈಬ್ರರಿಯನ್ನು ಬಳಸಬಹುದು.
# ಇದರೊಂದಿಗೆ ಇನ್ಸ್ಟಾಲ್ ಮಾಡಿ: pip install py-cpuinfo
import cpuinfo
info = cpuinfo.get_cpu_info()
supported_flags = info.get('flags', [])
print("ಸಿಮ್ಡಿ ಬೆಂಬಲ:")
if 'avx512f' in supported_flags:
print("- AVX-512 ಬೆಂಬಲಿತವಾಗಿದೆ")
elif 'avx2' in supported_flags:
print("- AVX2 ಬೆಂಬಲಿತವಾಗಿದೆ")
elif 'avx' in supported_flags:
print("- AVX ಬೆಂಬಲಿತವಾಗಿದೆ")
elif 'sse4_2' in supported_flags:
print("- SSE4.2 ಬೆಂಬಲಿತವಾಗಿದೆ")
else:
print("- ಮೂಲಭೂತ SSE ಬೆಂಬಲ ಅಥವಾ ಹಳೆಯದು.")
ಇದು ಜಾಗತಿಕ ಸಂದರ್ಭದಲ್ಲಿ ನಿರ್ಣಾಯಕವಾಗಿದೆ, ಏಕೆಂದರೆ ಕ್ಲೌಡ್ ಕಂಪ್ಯೂಟಿಂಗ್ ಇನ್ಸ್ಟನ್ಸ್ಗಳು ಮತ್ತು ಬಳಕೆದಾರರ ಹಾರ್ಡ್ವೇರ್ ಪ್ರದೇಶಗಳಾದ್ಯಂತ ವ್ಯಾಪಕವಾಗಿ ಬದಲಾಗಬಹುದು. ಹಾರ್ಡ್ವೇರ್ ಸಾಮರ್ಥ್ಯಗಳನ್ನು ತಿಳಿದುಕೊಳ್ಳುವುದು ಕಾರ್ಯಕ್ಷಮತೆಯ ಗುಣಲಕ್ಷಣಗಳನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳಲು ಅಥವಾ ನಿರ್ದಿಷ್ಟ ಆಪ್ಟಿಮೈಸೇಶನ್ಗಳೊಂದಿಗೆ ಕೋಡ್ ಅನ್ನು ಕಂಪೈಲ್ ಮಾಡಲು ಸಹಾಯ ಮಾಡುತ್ತದೆ.
ಡೇಟಾ ಪ್ರಕಾರಗಳ ಪ್ರಾಮುಖ್ಯತೆ
ಸಿಮ್ಡಿ ಕಾರ್ಯಾಚರಣೆಗಳು ಡೇಟಾ ಪ್ರಕಾರಗಳಿಗೆ (`dtype` ನಂಪೈನಲ್ಲಿ) ಅತ್ಯಂತ ನಿರ್ದಿಷ್ಟವಾಗಿವೆ. ನಿಮ್ಮ ಸಿಮ್ಡಿ ರಿಜಿಸ್ಟರ್ನ ಅಗಲವು ಸ್ಥಿರವಾಗಿರುತ್ತದೆ. ಇದರರ್ಥ ನೀವು ಚಿಕ್ಕ ಡೇಟಾ ಪ್ರಕಾರವನ್ನು ಬಳಸಿದರೆ, ನೀವು ಒಂದೇ ರಿಜಿಸ್ಟರ್ನಲ್ಲಿ ಹೆಚ್ಚು ಅಂಶಗಳನ್ನು ಹೊಂದಿಸಬಹುದು ಮತ್ತು ಪ್ರತಿ ಸೂಚನೆಗೆ ಹೆಚ್ಚು ಡೇಟಾವನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಬಹುದು.
ಉದಾಹರಣೆಗೆ, 256-ಬಿಟ್ ಎವಿಎಕ್ಸ್ ರಿಜಿಸ್ಟರ್ ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳಬಹುದು:
- ನಾಲ್ಕು 64-ಬಿಟ್ ಫ್ಲೋಟಿಂಗ್-ಪಾಯಿಂಟ್ ಸಂಖ್ಯೆಗಳು (`float64` ಅಥವಾ `double`).
- ಎಂಟು 32-ಬಿಟ್ ಫ್ಲೋಟಿಂಗ್-ಪಾಯಿಂಟ್ ಸಂಖ್ಯೆಗಳು (`float32` ಅಥವಾ `float`).
ನಿಮ್ಮ ಅಪ್ಲಿಕೇಶನ್ನ ನಿಖರತೆಯ ಅವಶ್ಯಕತೆಗಳನ್ನು 32-ಬಿಟ್ ಫ್ಲೋಟ್ಗಳಿಂದ ಪೂರೈಸಬಹುದಾದರೆ, ನಿಮ್ಮ ನಂಪೈ ಅರೇಗಳ `dtype` ಅನ್ನು `np.float64` (ಅನೇಕ ಸಿಸ್ಟಮ್ಗಳಲ್ಲಿ ಡೀಫಾಲ್ಟ್) ನಿಂದ `np.float32` ಗೆ ಬದಲಾಯಿಸುವುದರಿಂದ ಎವಿಎಕ್ಸ್-ಸಕ್ರಿಯಗೊಳಿಸಿದ ಹಾರ್ಡ್ವೇರ್ನಲ್ಲಿ ನಿಮ್ಮ ಕಂಪ್ಯೂಟೇಶನಲ್ ಥ್ರೋಪುಟ್ ಅನ್ನು ದ್ವಿಗುಣಗೊಳಿಸಬಹುದು. ನಿಮ್ಮ ಸಮಸ್ಯೆಗೆ ಸಾಕಷ್ಟು ನಿಖರತೆಯನ್ನು ಒದಗಿಸುವ ಚಿಕ್ಕ ಡೇಟಾ ಪ್ರಕಾರವನ್ನು ಯಾವಾಗಲೂ ಆರಿಸಿ.
ಯಾವಾಗ ವೆಕ್ಟರೈಸ್ ಮಾಡಬಾರದು
ವೆಕ್ಟರೈಸೇಶನ್ ಒಂದು ಸಂಜೀವಿನಿಯಲ್ಲ. ಇದು ನಿಷ್ಪರಿಣಾಮಕಾರಿಯಾಗಿರುವ ಅಥವಾ ಪ್ರತಿಕೂಲವಾಗಿರುವ ಸನ್ನಿವೇಶಗಳಿವೆ:
- ಡೇಟಾ-ಅವಲಂಬಿತ ನಿಯಂತ್ರಣ ಹರಿವು: ಸಂಕೀರ್ಣ `if-elif-else` ಶಾಖೆಗಳನ್ನು ಹೊಂದಿರುವ ಲೂಪ್ಗಳು ಅನಿರೀಕ್ಷಿತವಾಗಿದ್ದು ಮತ್ತು ವಿಭಿನ್ನ ಕಾರ್ಯಗತಗೊಳಿಸುವ ಮಾರ್ಗಗಳಿಗೆ ಕಾರಣವಾಗುತ್ತವೆ, ಅವುಗಳನ್ನು ಕಂಪೈಲರ್ಗಳು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ವೆಕ್ಟರೈಸ್ ಮಾಡಲು ಬಹಳ ಕಷ್ಟ.
- ಅನುಕ್ರಮ ಅವಲಂಬನೆಗಳು: ಒಂದು ಅಂಶದ ಲೆಕ್ಕಾಚಾರವು ಹಿಂದಿನ ಅಂಶದ ಫಲಿತಾಂಶವನ್ನು ಅವಲಂಬಿಸಿದ್ದರೆ (ಉದಾ., ಕೆಲವು ಪುನರಾವರ್ತಿತ ಸೂತ್ರಗಳಲ್ಲಿ), ಸಮಸ್ಯೆಯು ಅಂತರ್ಗತವಾಗಿ ಅನುಕ್ರಮವಾಗಿರುತ್ತದೆ ಮತ್ತು ಸಿಮ್ಡಿಯೊಂದಿಗೆ ಸಮಾನಾಂತರಗೊಳಿಸಲಾಗುವುದಿಲ್ಲ.
- ಸಣ್ಣ ಡೇಟಾಸೆಟ್ಗಳು: ಬಹಳ ಸಣ್ಣ ಅರೇಗಳಿಗೆ (ಉದಾ., ಒಂದು ಡಜನ್ಗಿಂತ ಕಡಿಮೆ ಅಂಶಗಳು), ನಂಪೈನಲ್ಲಿ ವೆಕ್ಟರೈಸ್ಡ್ ಫಂಕ್ಷನ್ ಕರೆಯನ್ನು ಸ್ಥಾಪಿಸುವ ಓವರ್ಹೆಡ್ ಸರಳ, ನೇರ ಪೈಥಾನ್ ಲೂಪ್ನ ವೆಚ್ಚಕ್ಕಿಂತ ಹೆಚ್ಚಾಗಿರಬಹುದು.
- ಅನಿಯಮಿತ ಮೆಮೊರಿ ಪ್ರವೇಶ: ನಿಮ್ಮ ಅಲ್ಗಾರಿದಮ್ಗೆ ಮೆಮೊರಿಯಲ್ಲಿ ಅನಿರೀಕ್ಷಿತ ಮಾದರಿಯಲ್ಲಿ ಜಿಗಿಯುವ ಅಗತ್ಯವಿದ್ದರೆ, ಅದು ಸಿಪಿಯುನ ಕ್ಯಾಶ್ ಮತ್ತು ಪ್ರಿಫೆಚಿಂಗ್ ಯಾಂತ್ರಿಕ ವ್ಯವಸ್ಥೆಗಳನ್ನು ಸೋಲಿಸುತ್ತದೆ, ಸಿಮ್ಡಿಯ ಪ್ರಮುಖ ಪ್ರಯೋಜನವನ್ನು ನಿರರ್ಥಕಗೊಳಿಸುತ್ತದೆ.
ಕೇಸ್ ಸ್ಟಡಿ: ಸಿಮ್ಡಿಯೊಂದಿಗೆ ಇಮೇಜ್ ಪ್ರೊಸೆಸಿಂಗ್
ಈ ಪರಿಕಲ್ಪನೆಗಳನ್ನು ಪ್ರಾಯೋಗಿಕ ಉದಾಹರಣೆಯೊಂದಿಗೆ ಗಟ್ಟಿಗೊಳಿಸೋಣ: ಬಣ್ಣದ ಚಿತ್ರವನ್ನು ಗ್ರೇಸ್ಕೇಲ್ಗೆ ಪರಿವರ್ತಿಸುವುದು. ಒಂದು ಚಿತ್ರವು ಕೇವಲ 3ಡಿ ಸಂಖ್ಯೆಗಳ ಅರೇ (ಎತ್ತರ x ಅಗಲ x ಬಣ್ಣ ಚಾನಲ್ಗಳು), ಇದು ವೆಕ್ಟರೈಸೇಶನ್ಗೆ ಪರಿಪೂರ್ಣ ಅಭ್ಯರ್ಥಿಯಾಗಿದೆ.
ಪ್ರಕಾಶಮಾನತೆಗೆ ಒಂದು ಪ್ರಮಾಣಿತ ಸೂತ್ರ: `ಗ್ರೇಸ್ಕೇಲ್ = 0.299 * R + 0.587 * G + 0.114 * B`.
ನಾವು `(1920, 1080, 3)` ಆಕಾರ ಮತ್ತು `uint8` ಡೇಟಾ ಪ್ರಕಾರದೊಂದಿಗೆ ನಂಪೈ ಅರೇ ಆಗಿ ಲೋಡ್ ಮಾಡಲಾದ ಚಿತ್ರವನ್ನು ಹೊಂದಿದ್ದೇವೆ ಎಂದು ಭಾವಿಸೋಣ.
ವಿಧಾನ 1: ಶುದ್ಧ ಪೈಥಾನ್ ಲೂಪ್ (ನಿಧಾನವಾದ ದಾರಿ)
def to_grayscale_python(image):
h, w, _ = image.shape
grayscale_image = np.zeros((h, w), dtype=np.uint8)
for r in range(h):
for c in range(w):
pixel = image[r, c]
gray_value = 0.299 * pixel[0] + 0.587 * pixel[1] + 0.114 * pixel[2]
grayscale_image[r, c] = int(gray_value)
return grayscale_image
ಇದು ಮೂರು ನೆಸ್ಟೆಡ್ ಲೂಪ್ಗಳನ್ನು ಒಳಗೊಂಡಿರುತ್ತದೆ ಮತ್ತು ಹೆಚ್ಚಿನ ರೆಸಲ್ಯೂಶನ್ ಚಿತ್ರಕ್ಕೆ ನಂಬಲಾಗದಷ್ಟು ನಿಧಾನವಾಗಿರುತ್ತದೆ.
ವಿಧಾನ 2: ನಂಪೈ ವೆಕ್ಟರೈಸೇಶನ್ (ವೇಗದ ದಾರಿ)
def to_grayscale_numpy(image):
# R, G, B ಚಾನಲ್ಗಳಿಗೆ ತೂಕವನ್ನು ವಿವರಿಸಿ
weights = np.array([0.299, 0.587, 0.114])
# ಕೊನೆಯ ಅಕ್ಷದ ಉದ್ದಕ್ಕೂ (ಬಣ್ಣ ಚಾನಲ್ಗಳು) ಡಾಟ್ ಉತ್ಪನ್ನವನ್ನು ಬಳಸಿ
grayscale_image = np.dot(image[...,:3], weights).astype(np.uint8)
return grayscale_image
ಈ ಆವೃತ್ತಿಯಲ್ಲಿ, ನಾವು ಡಾಟ್ ಉತ್ಪನ್ನವನ್ನು ನಿರ್ವಹಿಸುತ್ತೇವೆ. ನಂಪೈನ `np.dot` ಹೆಚ್ಚು ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲ್ಪಟ್ಟಿದೆ ಮತ್ತು ಅನೇಕ ಪಿಕ್ಸೆಲ್ಗಳಿಗೆ R, G, B ಮೌಲ್ಯಗಳನ್ನು ಏಕಕಾಲದಲ್ಲಿ ಗುಣಿಸಲು ಮತ್ತು ಸಂಕಲಿಸಲು ಸಿಮ್ಡಿ ಬಳಸುತ್ತದೆ. ಕಾರ್ಯಕ್ಷಮತೆಯ ವ್ಯತ್ಯಾಸವು ಹಗಲು-ರಾತ್ರಿಯಷ್ಟು ಇರುತ್ತದೆ—ಸುಲಭವಾಗಿ 100 ಪಟ್ಟು ಅಥವಾ ಹೆಚ್ಚು ವೇಗವಾಗಿರುತ್ತದೆ.
ಭವಿಷ್ಯ: ಸಿಮ್ಡಿ ಮತ್ತು ಪೈಥಾನ್ನ ವಿಕಾಸಗೊಳ್ಳುತ್ತಿರುವ ಭೂದೃಶ್ಯ
ಉನ್ನತ-ಕಾರ್ಯಕ್ಷಮತೆಯ ಪೈಥಾನ್ ಪ್ರಪಂಚವು ನಿರಂತರವಾಗಿ ವಿಕಸನಗೊಳ್ಳುತ್ತಿದೆ. ಅನೇಕ ಥ್ರೆಡ್ಗಳು ಪೈಥಾನ್ ಬೈಟ್ಕೋಡ್ ಅನ್ನು ಸಮಾನಾಂತರವಾಗಿ ಕಾರ್ಯಗತಗೊಳಿಸುವುದನ್ನು ತಡೆಯುವ ಕುಖ್ಯಾತ ಗ್ಲೋಬಲ್ ಇಂಟರ್ಪ್ರಿಟರ್ ಲಾಕ್ (GIL) ಗೆ ಸವಾಲು ಹಾಕಲಾಗುತ್ತಿದೆ. GIL ಅನ್ನು ಐಚ್ಛಿಕವಾಗಿಸುವ ಗುರಿಯನ್ನು ಹೊಂದಿರುವ ಯೋಜನೆಗಳು ಸಮಾನಾಂತರತೆಗೆ ಹೊಸ ಮಾರ್ಗಗಳನ್ನು ತೆರೆಯಬಹುದು. ಆದಾಗ್ಯೂ, ಸಿಮ್ಡಿ ಉಪ-ಕೋರ್ ಮಟ್ಟದಲ್ಲಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ ಮತ್ತು GIL ನಿಂದ ಪ್ರಭಾವಿತವಾಗುವುದಿಲ್ಲ, ಇದು ವಿಶ್ವಾಸಾರ್ಹ ಮತ್ತು ಭವಿಷ್ಯ-ನಿರೋಧಕ ಆಪ್ಟಿಮೈಸೇಶನ್ ತಂತ್ರವಾಗಿದೆ.
ಹಾರ್ಡ್ವೇರ್ ಹೆಚ್ಚು ವೈವಿಧ್ಯಮಯವಾಗುತ್ತಿದ್ದಂತೆ, ವಿಶೇಷ ವೇಗವರ್ಧಕಗಳು ಮತ್ತು ಹೆಚ್ಚು ಶಕ್ತಿಯುತ ವೆಕ್ಟರ್ ಘಟಕಗಳೊಂದಿಗೆ, ಹಾರ್ಡ್ವೇರ್ ವಿವರಗಳನ್ನು ಅಮೂರ್ತಗೊಳಿಸುವ ಮತ್ತು ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ನೀಡುವ ಉಪಕರಣಗಳು—ನಂಪೈ ಮತ್ತು ನಂಬಾದಂತಹವು—ಇನ್ನೂ ಹೆಚ್ಚು ನಿರ್ಣಾಯಕವಾಗುತ್ತವೆ. ಸಿಪಿಯುನೊಳಗಿನ ಸಿಮ್ಡಿಯಿಂದ ಮುಂದಿನ ಹಂತವು ಸಾಮಾನ್ಯವಾಗಿ ಜಿಪಿಯುನಲ್ಲಿ ಸಿಮ್ಟಿ (ಸಿಂಗಲ್ ಇನ್ಸ್ಟ್ರಕ್ಷನ್, ಮಲ್ಟಿಪಲ್ ಥ್ರೆಡ್ಗಳು), ಮತ್ತು ಕ್ಯೂಪೈ (NVIDIA ಜಿಪಿಯುಗಳಲ್ಲಿ ನಂಪೈಗೆ ಡ್ರಾಪ್-ಇನ್ ಬದಲಿ) ನಂತಹ ಲೈಬ್ರರಿಗಳು ಇದೇ ವೆಕ್ಟರೈಸೇಶನ್ ತತ್ವಗಳನ್ನು ಇನ್ನೂ ದೊಡ್ಡ ಪ್ರಮಾಣದಲ್ಲಿ ಅನ್ವಯಿಸುತ್ತವೆ.
ತೀರ್ಮಾನ: ವೆಕ್ಟರ್ ಅನ್ನು ಅಪ್ಪಿಕೊಳ್ಳಿ
ನಾವು ಸಿಪಿಯುನ ತಿರುಳಿನಿಂದ ಪೈಥಾನ್ನ ಉನ್ನತ-ಮಟ್ಟದ ಅಮೂರ್ತತೆಗಳವರೆಗೆ ಪ್ರಯಾಣಿಸಿದ್ದೇವೆ. ಪ್ರಮುಖ ಅಂಶವೆಂದರೆ ಪೈಥಾನ್ನಲ್ಲಿ ವೇಗದ ಸಂಖ್ಯಾತ್ಮಕ ಕೋಡ್ ಬರೆಯಲು, ನೀವು ಲೂಪ್ಗಳಲ್ಲಿ ಅಲ್ಲ, ಅರೇಗಳಲ್ಲಿ ಯೋಚಿಸಬೇಕು. ಇದೇ ವೆಕ್ಟರೈಸೇಶನ್ನ ಸಾರ.
ನಮ್ಮ ಪ್ರಯಾಣವನ್ನು ಸಂಕ್ಷಿಪ್ತಗೊಳಿಸೋಣ:
- ಸಮಸ್ಯೆ: ಇಂಟರ್ಪ್ರಿಟರ್ ಓವರ್ಹೆಡ್ನಿಂದಾಗಿ ಶುದ್ಧ ಪೈಥಾನ್ ಲೂಪ್ಗಳು ಸಂಖ್ಯಾತ್ಮಕ ಕಾರ್ಯಗಳಿಗೆ ನಿಧಾನವಾಗಿವೆ.
- ಹಾರ್ಡ್ವೇರ್ ಪರಿಹಾರ: ಸಿಮ್ಡಿ ಒಂದೇ ಸಿಪಿಯು ಕೋರ್ಗೆ ಒಂದೇ ಕಾರ್ಯಾಚರಣೆಯನ್ನು ಏಕಕಾಲದಲ್ಲಿ ಅನೇಕ ಡೇಟಾ ಪಾಯಿಂಟ್ಗಳ ಮೇಲೆ ನಿರ್ವಹಿಸಲು ಅನುವು ಮಾಡಿಕೊಡುತ್ತದೆ.
- ಪ್ರಾಥಮಿಕ ಪೈಥಾನ್ ಉಪಕರಣ: ನಂಪೈ ವೆಕ್ಟರೈಸೇಶನ್ನ ಮೂಲಾಧಾರವಾಗಿದೆ, ಇದು ಒಂದು ಅರ್ಥಗರ್ಭಿತ ಅರೇ ಆಬ್ಜೆಕ್ಟ್ ಮತ್ತು ಆಪ್ಟಿಮೈಸ್ ಮಾಡಿದ, ಸಿಮ್ಡಿ-ಸಕ್ರಿಯಗೊಳಿಸಿದ ಸಿ/ಫೋರ್ಟ್ರಾನ್ ಕೋಡ್ ಆಗಿ ಕಾರ್ಯಗತಗೊಳ್ಳುವ ufuncs ನ ಶ್ರೀಮಂತ ಲೈಬ್ರರಿಯನ್ನು ಒದಗಿಸುತ್ತದೆ.
- ಸುಧಾರಿತ ಉಪಕರಣಗಳು: ನಂಪೈನಲ್ಲಿ ಸುಲಭವಾಗಿ ವ್ಯಕ್ತಪಡಿಸಲಾಗದ ಕಸ್ಟಮ್ ಅಲ್ಗಾರಿದಮ್ಗಳಿಗಾಗಿ, ನಂಬಾ ನಿಮ್ಮ ಲೂಪ್ಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲು JIT ಕಂಪೈಲೇಶನ್ ಅನ್ನು ಒದಗಿಸುತ್ತದೆ, ಆದರೆ ಸೈಥಾನ್ ಪೈಥಾನ್ ಅನ್ನು ಸಿ ಯೊಂದಿಗೆ ಸಂಯೋಜಿಸುವ ಮೂಲಕ ಸೂಕ್ಷ್ಮ-ಹಂತದ ನಿಯಂತ್ರಣವನ್ನು ನೀಡುತ್ತದೆ.
- ಮನಸ್ಥಿತಿ: ಪರಿಣಾಮಕಾರಿ ಆಪ್ಟಿಮೈಸೇಶನ್ಗೆ ಡೇಟಾ ಪ್ರಕಾರಗಳು, ಮೆಮೊರಿ ಮಾದರಿಗಳನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವುದು ಮತ್ತು ಕೆಲಸಕ್ಕೆ ಸರಿಯಾದ ಸಾಧನವನ್ನು ಆರಿಸುವುದು ಅಗತ್ಯವಾಗಿರುತ್ತದೆ.
ಮುಂದಿನ ಬಾರಿ ನೀವು ದೊಡ್ಡ ಸಂಖ್ಯೆಗಳ ಪಟ್ಟಿಯನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು `for` ಲೂಪ್ ಬರೆಯುವಾಗ, ನಿಲ್ಲಿಸಿ ಮತ್ತು ಕೇಳಿ: "ಇದನ್ನು ವೆಕ್ಟರ್ ಕಾರ್ಯಾಚರಣೆಯಾಗಿ ವ್ಯಕ್ತಪಡಿಸಬಹುದೇ?" ಈ ವೆಕ್ಟರೈಸ್ಡ್ ಮನಸ್ಥಿತಿಯನ್ನು ಅಳವಡಿಸಿಕೊಳ್ಳುವ ಮೂಲಕ, ನೀವು ಆಧುನಿಕ ಹಾರ್ಡ್ವೇರ್ನ ನಿಜವಾದ ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ಅನ್ಲಾಕ್ ಮಾಡಬಹುದು ಮತ್ತು ನಿಮ್ಮ ಪೈಥಾನ್ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಹೊಸ ಮಟ್ಟದ ವೇಗ ಮತ್ತು ದಕ್ಷತೆಗೆ ಏರಿಸಬಹುದು, ನೀವು ಜಗತ್ತಿನ ಯಾವುದೇ ಮೂಲೆಯಲ್ಲಿ ಕೋಡಿಂಗ್ ಮಾಡುತ್ತಿದ್ದರೂ ಸಹ.